<template>
  <div class="main">
    <a-form
      class="user-layout-login"
      ref="formIns"
      :model="state.formData"
      :rules="state.formRules"
      validateTrigger="blur"
    >
      <a-tabs :tabBarStyle="{ textAlign: 'center', borderBottom: 'unset' }">
        <a-tab-pane key="account" tab="账号密码登录">
          <a-form-item name="account">
            <a-input
              v-model:value.trim="state.formData.account"
              size="large"
              type="text"
              placeholder="请输入账号"
            >
              <template #prefix><user-outlined /></template>
            </a-input>
          </a-form-item>
          <a-form-item name="password">
            <a-input-password
              v-model:value.trim="state.formData.password"
              size="large"
              placeholder="请输入密码"
            >
              <template #prefix><lock-outlined /></template>
            </a-input-password>
          </a-form-item>
          <a-row :gutter="16">
            <a-col :span="16">
              <a-form-item name="captcha">
                <a-input
                  v-model:value.trim="state.formData.captcha"
                  size="large"
                  type="text"
                  placeholder="请输入验证码"
                >
                  <template #prefix><mail-outlined /></template>
                </a-input>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <!--验证码-->
              <div class="captcha" @click="getCaptchaImg">
                <img v-if="state.image.url" :src="state.image.url" alt="" />
                <a-spin
                  v-if="state.image.loading"
                  size="small"
                  tip="加载中..."
                />
              </div>
            </a-col>
          </a-row>
        </a-tab-pane>
      </a-tabs>

      <a-form-item name="remember">
        <a-checkbox v-model:checked="state.formData.remember">
          记住密码
        </a-checkbox>
      </a-form-item>
      <a-form-item style="margin-top: 24px">
        <ButtonAgain
          class="login-button"
          type="primary"
          size="large"
          @click="submit"
        >
          登录
        </ButtonAgain>
      </a-form-item>
    </a-form>
  </div>
</template>

<script setup>
import { UserOutlined, LockOutlined, MailOutlined } from '@ant-design/icons-vue'
import { storage } from '@/utils'
import { useAutoImport } from '@/hooks/autoImport'

const { reactive, ref, onBeforeMount, $store, $route, $router, message, API } =
  useAutoImport()

//验证码校验
const captchaValidator = (_, value) => {
  if (value.length === 0) {
    return Promise.reject('验证码不能为空')
  }
  return Promise.resolve()
}
//密码校验
const passwordValidator = (_, value) => {
  if (value.length === 0) return Promise.reject('密码不能为空~')
  if (value === secret) return Promise.resolve()
  if (!/^.{6,16}$/.test(value)) return Promise.reject('密码长度为6~16位~')
  return Promise.resolve()
}

const formIns = ref(null)
const state = reactive({
  formData: {
    account: '',
    password: '',
    captcha: '',
    remember: true,
  },
  formRules: {
    account: [{ required: true, message: '账号不能为空~' }],
    password: [{ validator: passwordValidator }],
    captcha: [{ validator: captchaValidator }],
  },
  //服务器返回的验证码图片
  image: {
    url: '',
    uuid: '',
    loading: false,
  },
})
//定义记住密码情况下的初始状态
let secret = '********'
let originPassword = ''

onBeforeMount(() => {
  //获取验证码
  getCaptchaImg()
  //页面渲染之前判断是否记住密码
  let remember = storage.get('REMEMBER')
  if (!remember) return
  state.formData.account = remember.account
  //占位
  state.formData.password = secret
  //获取存储的密码
  originPassword = remember.password
})

//发请求获取验证码
const getCaptchaImg = async () => {
  //如果已在loading状态中就不再发请求
  if (state.image.loading) return
  state.image.loading = true
  try {
    let { code, img, uuid } = await API.reqGetCaptchaImage()
    if (+code === 200) {
      state.image.uuid = uuid
      state.image.url = `data:image/gif;base64,${img}`
    } else {
      message.error('获取验证码失败,请稍后再试~')
    }
  } catch (_) {}
  state.image.loading = false
}

//表单提交
const submit = async () => {
  try {
    let {
      formData: { account, password, captcha, remember },
      image: { uuid },
    } = state
    //触发表单校验
    await formIns.value.validate()
    //验证密码是否是占位符还是用户自己输入
    if (password === secret) {
      //用户未修改密码,那直接获取本地存储的密码登录
      password = originPassword
    } else {
      //用户自己修改了密码->md5加密->登录 (此项目不涉及)
    }

    let { code, token, msg } = await API.reqUserLogin({
      username: account,
      password,
      code: captcha,
      uuid,
    })
    if (+code === 200) {
      //登陆成功，存token/存用户信息到vuex/记住账号密码/跳转
      storage.set('TOKEN', token)
      await $store.dispatch('user/getProfile')
      //记住账号密码
      if (remember) {
        storage.set('REMEMBER', {
          account,
          password,
        })
      } else {
        storage.remove('REMEMBER')
      }
      message.success('登录成功~')
      let to = $route.query.to
      to ? $router.replace(decodeURIComponent(to)) : $router.push('/')
    } else {
      message.error(msg)
      state.formData.captcha = ''
      await getCaptchaImg()
    }
  } catch (_) {}
}
</script>

<style lang="less" scoped>
.main {
  min-width: 260px;
  width: 368px;
  margin: 0 auto;
}

.user-layout-login {
  label {
    font-size: 14px;
  }

  .getCaptcha {
    display: block;
    width: 100%;
    height: 40px;
  }

  button.login-button {
    padding: 0 15px;
    font-size: 16px;
    height: 40px;
    width: 100%;
  }

  :deep(.ant-input-prefix) {
    color: rgba(0, 0, 0, 0.25);
  }

  .captcha {
    position: relative;
    height: 40px;
    background: #ddd;

    .ant-spin {
      position: absolute;
      top: 50%;
      left: 50%;
      z-index: 10;
      transform: translate(-50%, -50%);

      :deep(.ant-spin-text) {
        font-size: 12px;
      }
    }

    img {
      display: block;
      width: 100%;
      height: 100%;
    }
  }
}
</style>
